package com.noah.common.redis.config.auto;

import com.noah.common.redis.config.RedissonConfig;
import com.noah.common.redis.utility.RedisReactiveUtility;
import org.redisson.api.RedissonClient;
import org.redisson.api.RedissonReactiveClient;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.core.io.ResourceLoader;
import org.springframework.data.redis.connection.ReactiveRedisConnection;
import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import reactor.core.publisher.Flux;

/**
 * @author noah
 * 2023/9/7 19:05
 */
@AutoConfiguration
@ComponentScan(basePackages = {"com.noah.common.redis"})
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
@ConditionalOnClass({
        RedissonConfig.class,
        ReactiveRedisConnection.class,
        ReactiveRedisTemplate.class,
        Flux.class
})
public class RedisReactiveAutoConfig {

    @Bean
    @ConditionalOnMissingBean(name = "reactiveRedisTemplate")
    public ReactiveRedisTemplate<Object, Object> reactiveRedisTemplate(
            ReactiveRedisConnectionFactory reactiveRedisConnectionFactory,
            ResourceLoader resourceLoader
    ) {
        JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer(
                resourceLoader.getClassLoader()
        );
        RedisSerializationContext<Object, Object> serializationContext = RedisSerializationContext.newSerializationContext()
                .key(jdkSerializationRedisSerializer).value(jdkSerializationRedisSerializer)
                .hashKey(jdkSerializationRedisSerializer)
                .hashValue(jdkSerializationRedisSerializer).build();
        return new ReactiveRedisTemplate<>(reactiveRedisConnectionFactory, serializationContext);
    }

    @Bean
    @ConditionalOnMissingBean(name = "reactiveStringRedisTemplate")
    public ReactiveStringRedisTemplate reactiveStringRedisTemplate(
            ReactiveRedisConnectionFactory reactiveRedisConnectionFactory
    ) {
        return new ReactiveStringRedisTemplate(reactiveRedisConnectionFactory);
    }

    @Bean(destroyMethod = "shutdown")
    @ConditionalOnMissingBean(RedissonReactiveClient.class)
    public RedissonReactiveClient redissonReactiveClient(
            RedissonClient redissonClient
    ) {
        return redissonClient.reactive();
    }

    @Bean
    @ConditionalOnMissingBean(RedisReactiveUtility.class)
    public RedisReactiveUtility redisReactiveUtility(RedissonReactiveClient redissonReactiveClient) {
        return new RedisReactiveUtility(redissonReactiveClient);
    }

}
